#!/usr/bin/perl
#
# Script to generate C++ traits classes for all X-Plane datarefs.
#
# Copyright 2012 the VATSIM Connector project.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

use strict;
use warnings;

sub usage
{
  print STDERR <<"EOF";
This program generates C++ traits classes that describe the data refs available
to X-Plane plugins.
Usage:
  $0 <XPLANEPATH>
Arguments:
  <XPLANEPATH> - folder in which X-Plane is installed
EOF
  exit 1;
}

@ARGV == 1 or usage();

my $filename = "$ARGV[0]/Resources/plugins/DataRefs.txt";

my $fh;
unless (open $fh, '<', $filename)
{
  print STDERR "$filename: $!\n";
  usage();
}

my %hierarchy;

while (<$fh>)
{
  chomp;
  next unless m"\t";

  my @fields = split "\t";
  next unless @fields >= 3;
  
  my($dataref, $type, $canwrite, $extra, $comment) = @fields;
  $canwrite = $canwrite eq 'y' ? 'true' : 'false';
  $comment ||= 'Undocumented dataref';
  my $size;
  $type =~ m"(\w+)\[(\d+)\]" and ($type, $size) = ($1, $2);
  
  my @namespaces = split '/', $dataref;
  my $class = pop @namespaces;
  $class =~ s(\])()g;
  $class =~ s(\[)(_)g;
  $class =~ s((plane\d+)_sla1_ratio)(${1}_slat_ratio);
  $class eq 'type' and $class .= '_';
  
  my $namespace = \%hierarchy;
  $namespace = ($namespace->{$_} ||= {}) foreach @namespaces;
  
  $namespace->{$class} = [$dataref, $type, $size, $canwrite, $extra, $comment];
}

close $fh;

our $indent = '  ';
print <<"EOF";
// This file automatically generated from DataRefs.txt by $0
namespace xplane
{
${indent}namespace data
${indent}{
EOF

recurse(\%hierarchy, 2);

print <<"EOF";
${indent}}
}
EOF

sub recurse
{
  my($hash, $indentLevel) = @_;
  
  my $in = $indent x $indentLevel;
  foreach my $key (sort keys %$hash)
  {
    if (ref $hash->{$key} eq 'HASH')
    {
      print <<"EOF";
${in}namespace $key
${in}{
EOF

      recurse($hash->{$key}, $indentLevel + 1);
      
      print <<"EOF";
${in}}
EOF
    }
    else
    {
      my($name, $type, $size, $canwrite, $extra, $comment) = @{ $hash->{$key} };
      
      defined $extra and $extra ne '???' and $comment .= " ($extra)";
      
      print <<"EOF";
${in}/// $comment
${in}class $key
${in}{
${in}public:
${in}${indent}static char const* name() { return "$name"; }
${in}${indent}static bool const canwrite = $canwrite;
EOF

      print <<"EOF" if $type =~ m(int|float|double);
${in}${indent}typedef $type type;
EOF

      print <<"EOF" if defined $size;
${in}${indent}static size_t const size = $size;
EOF

      print <<"EOF";
${in}};
EOF
    }
  }
}